class WebGLYuvShowV2 {
    constructor(e) {
        this.canvas = e;
        this.gl = e.getContext("webgl") || e.getContext("experimental-webgl");
        this._init();
        this.showindex = 0
    }
    renderFrame(e, r, t) {
        if (this.canvas.width != e || this.canvas.height != r) {
            this.canvas.width = e;
            this.canvas.height = r
        }
        let a = this.gl;
        a.viewport(0, 0, e, r);
        a.clearColor(0, 0, 0, 0);
        a.clear(a.COLOR_BUFFER_BIT);
        let o = e * r;
        let i = (e >> 1) * (r >> 1);
        a.bindTexture(a.TEXTURE_2D, a.y);
        a.texImage2D(a.TEXTURE_2D, 0, a.LUMINANCE, e, r, 0, a.LUMINANCE, a.UNSIGNED_BYTE, t.subarray(0, o));
        a.bindTexture(a.TEXTURE_2D, a.u);
        a.texImage2D(a.TEXTURE_2D, 0, a.LUMINANCE, e >> 1, r >> 1, 0, a.LUMINANCE, a.UNSIGNED_BYTE, t.subarray(o, o + i));
        a.bindTexture(a.TEXTURE_2D, a.v);
        a.texImage2D(a.TEXTURE_2D, 0, a.LUMINANCE, e >> 1, r >> 1, 0, a.LUMINANCE, a.UNSIGNED_BYTE, t.subarray(o + i, t.length));
        a.drawArrays(a.TRIANGLE_STRIP, 0, 4)
    }
    clear() {
        let e = this.gl;
        e.clearColor(0, 0, 0, 0);
        e.clear(e.COLOR_BUFFER_BIT)
    }
    setSize(e, r, t) {
        let a = Math.min(t, e);
        this.canvas.width = a;
        this.canvas.height = a * r / e
    }
    destroy() {
        const { gl: e } = this;
        e.clear(e.COLOR_BUFFER_BIT | e.DEPTH_BUFFER_BIT | e.STENCIL_BUFFER_BIT)
    }
    _init() {
        let e = this.gl;
        if (!e) {
            console.log("gl not support！");
            return
        }
        e.pixelStorei(e.UNPACK_ALIGNMENT, 1);
        let r = `
            attribute lowp vec4 a_vertexPosition;
            attribute vec2 a_texturePosition;
            varying vec2 v_texCoord;
            void main() {
                gl_Position = a_vertexPosition;
                v_texCoord = a_texturePosition;
            }
        `;
        let t = `
            precision lowp float;
            uniform sampler2D samplerY;
            uniform sampler2D samplerU;
            uniform sampler2D samplerV;
            varying vec2 v_texCoord;
            void main() {
                float r,g,b,y,u,v,fYmul;
                y = texture2D(samplerY, v_texCoord).r;
                u = texture2D(samplerU, v_texCoord).r;
                v = texture2D(samplerV, v_texCoord).r;

                fYmul = y * 1.1643828125;
                r = fYmul + 1.59602734375 * v - 0.870787598;
                g = fYmul - 0.39176171875 * u - 0.81296875 * v + 0.52959375;
                b = fYmul + 2.01723046875 * u - 1.081389160375;
                gl_FragColor = vec4(r, g, b, 1.0);
            }
        `;
        let a = this._compileShader(r, e.VERTEX_SHADER);
        let o = this._compileShader(t, e.FRAGMENT_SHADER);
        let i = this._createProgram(a, o);
        this._initVertexBuffers(i);
        e.activeTexture(e.TEXTURE0);
        e.y = this._createTexture();
        e.uniform1i(e.getUniformLocation(i, "samplerY"), 0);
        e.activeTexture(e.TEXTURE1);
        e.u = this._createTexture();
        e.uniform1i(e.getUniformLocation(i, "samplerU"), 1);
        e.activeTexture(e.TEXTURE2);
        e.v = this._createTexture();
        e.uniform1i(e.getUniformLocation(i, "samplerV"), 2)
    }
    _initVertexBuffers(e) {
        let r = this.gl;
        let t = r.createBuffer();
        let a = new Float32Array([1, 1, 0, -1, 1, 0, 1, -1, 0, -1, -1, 0]);
        r.bindBuffer(r.ARRAY_BUFFER, t);
        r.bufferData(r.ARRAY_BUFFER, a, r.STATIC_DRAW);
        let o = r.getAttribLocation(e, "a_vertexPosition");
        r.vertexAttribPointer(o, 3, r.FLOAT, false, 0, 0);
        r.enableVertexAttribArray(o);
        let i = new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]);
        let d = r.createBuffer();
        r.bindBuffer(r.ARRAY_BUFFER, d);
        r.bufferData(r.ARRAY_BUFFER, i, r.STATIC_DRAW);
        let u = r.getAttribLocation(e, "a_texturePosition");
        r.vertexAttribPointer(u, 2, r.FLOAT, false, 0, 0);
        r.enableVertexAttribArray(u)
    }
    _compileShader(e, r) {
        let t = this.gl.createShader(r);
        this.gl.shaderSource(t, e);
        this.gl.compileShader(t);
        const a = this.gl.getShaderParameter(t, this.gl.COMPILE_STATUS);
        if (!a) {
            let e = this.gl.getShaderInfoLog(t);
            this.gl.deleteShader(t);
            console.error("could not compile shader", e);
            return
        }
        return t
    }
    _createProgram(e, r) {
        const t = this.gl;
        let a = t.createProgram();
        t.attachShader(a, e);
        t.attachShader(a, r);
        t.linkProgram(a);
        t.useProgram(a);
        const o = this.gl.getProgramParameter(a, this.gl.LINK_STATUS);
        if (!o) {
            console.err("program fail to link" + this.gl.getShaderInfoLog(a));
            return
        }
        return a
    }
    _createTexture(e = this.gl.LINEAR) {
        let r = this.gl;
        let t = r.createTexture();
        r.bindTexture(r.TEXTURE_2D, t);
        r.texParameteri(r.TEXTURE_2D, r.TEXTURE_WRAP_S, r.CLAMP_TO_EDGE);
        r.texParameteri(r.TEXTURE_2D, r.TEXTURE_WRAP_T, r.CLAMP_TO_EDGE);
        r.texParameteri(r.TEXTURE_2D, r.TEXTURE_MIN_FILTER, e);
        r.texParameteri(r.TEXTURE_2D, r.TEXTURE_MAG_FILTER, e);
        return t
    }
}
CvNetVideo = {
    decoder_id: -1,
    buffer: [],
    wasmOK: false
};
CvNetVideo.JXRGB = function (e, r, t, a, o) {
    if (CvNetVideo.firstrgb) {
        postMessage({
            type: 1
        });
        CvNetVideo.firstrgb = false
    }
    if (CvNetVideo.webglv2 == undefined) {
        var i = Module.HEAPU32[a / 4];
        var d = Module.HEAPU8.subarray(i, i + o);
        var u = new Uint8Array(new ArrayBuffer(o));
        u.set(d);
        postMessage({
            type: 3,
            id: e,
            data: u,
            width: r,
            height: t,
            pid: CvNetVideo.pid
        }, [u.buffer])
    } else {
        var n = Module.HEAPU32[a / 4];
        var l = Module.HEAPU8.subarray(n, n + o);
        CvNetVideo.webglv2.renderFrame(r, t, l);
        postMessage({
            type: 2,
            pid: CvNetVideo.pid
        })
    }
};
onmessage = function (e) {
    switch (e.data.t) {
        case 1:
            init(e.data.libffmpegUrl);
            if (e.data.canvas != undefined) {
                CvNetVideo.offcanvas = e.data.canvas;
                CvNetVideo.webglv2 = new WebGLYuvShowV2(e.data.canvas)
            }
            break;
        case 2:
            CvNetVideo.pid = e.data.id;
            break;
        case 3:
            if (CvNetVideo.wasmOK) {
                if (CvNetVideo.buffer.length > 0) {
                    for (var r = 0; r < CvNetVideo.buffer.length; r++) {
                        decode(CvNetVideo.buffer[r].p, CvNetVideo.buffer[r].a)
                    }
                    CvNetVideo.buffer = []
                }
                decode(e.data.p, e.data.a)
            } else {
                if (e.data.x == 0) {
                    CvNetVideo.buffer = []
                }
                CvNetVideo.buffer.push({
                    p: e.data.p,
                    a: e.data.a
                })
            }
            break;
        case 4:
            stop();
            break;
        case 5:
            if (CvNetVideo.decoder_id >= 0) {
                CvNetVideo.WASM.VideoDecoderFlush(CvNetVideo.decoder_id)
            }
            break;
        default:
    }
};
function init(r) {
    CvNetVideo.firstrgb = true;
    Module = typeof Module !== "undefined" ? Module : {};
    Module["locateFile"] = function () {
        let e = r.substr(0, r.lastIndexOf("/") + 1) + "libffmpeg.wasm";
        return e
    };
    importScripts(r);
    CvNetVideo.WASM = {
        FfmpegInit: Module["cwrap"]("FfmpegInit", "number"),
        CreateAVideoDecoder: Module["cwrap"]("CreateAVideoDecoder", "number", ["number", "number"]),
        VideoDecoderDecode: Module["cwrap"]("VideoDecoderDecode", "number", ["number", "array", "number"]),
        VideoDecoderFlush: Module["cwrap"]("VideoDecoderFlush", "number", ["number"]),
        VideoDecoderClear: Module["cwrap"]("VideoDecoderClear", "number", ["number"]),
        CreateAAudioEncoder: Module["cwrap"]("CreateAAudioEncoder", "number", ["number", "number", "number", "number", "number", "number", "number", "number", "number"]),
        AudioEncoderEncode: Module["cwrap"]("AudioEncoderEncode", "number", ["number", "array", "number"]),
        AudioEncoderClear: Module["cwrap"]("AudioEncoderClear", "number", ["number"]),
        CreateAAudioDecoder: Module["cwrap"]("CreateAAudioDecoder", "number", ["number", "number", "number", "number", "number", "number"]),
        AudioDecoderDecode: Module["cwrap"]("AudioDecoderDecode", "number", ["number", "array", "number"]),
        AudioDecoderFlush: Module["cwrap"]("AudioDecoderFlush", "number", ["number"]),
        AudioDecoderClear: Module["cwrap"]("AudioDecoderClear", "number", ["number"]),
        CreateAAacTranscoder: Module["cwrap"]("CreateAAacTranscoder", "number", ["number", "number", "number", "number"]),
        AacTranscoderTrans: Module["cwrap"]("AacTranscoderTrans", "number", ["number", "array", "number"]),
        AacTranscoderFlush: Module["cwrap"]("AacTranscoderFlush", "number", ["number"]),
        AacTranscoderClear: Module["cwrap"]("AacTranscoderClear", "number", ["number"]),
        CreateFMp4Muxer: Module["cwrap"]("CreateFMp4Muxer", "number", ["number", "number", "number", "number"]),
        FMp4Input1078Package: Module["cwrap"]("FMp4Input1078Package", "number", ["number", "array", "number"]),
        FMp4MuxClear: Module["cwrap"]("FMp4MuxClear", "number", ["number"]),
        JX_ADPCMA: 26,
        JX_H264: 98,
        AV_PIX_FMT_RGB24: 2,
        AV_PIX_FMT_ARGB: 27,
        AV_PIX_FMT_RGBA: 28,
        AV_PIX_FMT_YUV420: 29
    };
    addOnPostRun(function () {
        try {
            CvNetVideo.WASM.FfmpegInit();
            CvNetVideo.wasmOK = true
        } catch (e) {
            console.error(e)
        }
    });
    CvNetVideo.decoder_id = -1
};
function decode(e, r) {
    if (CvNetVideo.decoder_id == -1) {
        CvNetVideo.decoder_id = CvNetVideo.WASM.CreateAVideoDecoder(e, CvNetVideo.WASM.AV_PIX_FMT_YUV420)
    }
    if (CvNetVideo.decoder_id >= 0) {
        var t = new Uint8Array(r);
        CvNetVideo.WASM.VideoDecoderDecode(CvNetVideo.decoder_id, t, t.length)
    }
};
function stop() {
    CvNetVideo.firstrgb = true;
    if (CvNetVideo.webglv2) {
        CvNetVideo.webglv2.clear()
    }
    if (CvNetVideo.decoder_id != -1) {
        CvNetVideo.WASM.VideoDecoderClear(this.decoder_id);
        CvNetVideo.decoder_id = -1
    }
};
